/*
 * TreeContext.hpp
 *
 * Copyright 2012 Fabian Wenzelmann
 *
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 *
 * Recognition-Procedures-for-Boolean-Functions is free software: you
 * can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.
 *
 * If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef TREECONTEXT_HPP_
#define TREECONTEXT_HPP_

#include <cstddef>

#include <list>
#include <vector>
#include <iostream>

namespace bfr {

// forward declare the class
class SplittingTreeNode;

/**
 * A class that stores pointers to all nodes
 * sorted according column and row values.
 *
 * The SplittingTree class provides all required information itself.
 * But sometimes we want to ask for all the nodes in column 4.
 * This would be very inefficient in the recursive data structure,
 * but this class provides a faster way to obtain this.
 *
 * Note that both, column and row numbers, start with 0.
 */
class TreeContext {

	public:
            /**
             * The entries stored for each column.
             */
            typedef std::list<SplittingTreeNode*>* column_t;

            /**
             * The type that holds all information.
             */
            typedef std::vector<column_t> tree_t;

            /**
             * Iterator over the elements in a specific column.
             */
            typedef std::list<SplittingTreeNode*>::const_iterator
                    const_col_iterator;

            /**
             * Constructor.
             *
             * @param variableCount Number of variables that occur in
             * the DNF. The complete tree will have variableCount + 1 columns.
             */
            TreeContext(size_t variableCount);

            /**
             * Destructor.
             *
             * Will destroy only internal data, but <b>not</b> the nodes,
             * the SplittingTree will do this.
             *
             * @see SplittingTree#~SplittingTree
             */
            ~TreeContext();

            /**
             * Add a node to the context.
             *
             * The column will be read from the node
             * using SplittingTreeNode#getColumn.
             *
             * It returns the row of the node.
             *
             * @return Row of the node.
             */
            size_t addNode(SplittingTreeNode *node);

            /**
             * Return the number of columns in the tree.
             *
             * @return Number of columns.
             */
            size_t size() const;

            /**
             * Return the number of variables this context was created for.
             *
             * This should always be the same as #size - 1.
             *
             * @return Number of variables this context was created for.
             */
            size_t getVariableCount() const;

            /**
             * Return the number of nodes in a specific column.
             *
             * @param column Index of the column (0-based).
             *
             * @return Number of nodes in the specified column.
             */
            size_t getColumnSize(size_t column) const;

            /**
             * Return an iterator to the beginning in a specified column.
             *
             * This iterator can be used to iterate over all nodes in
             * the column.
             *
             * @return Iterator to the beginning of the specified column.
             */
            const_col_iterator columnBegin(size_t column) const;

            /**
             * Return an iterator to the end in a specified column.
             *
             * This iterators can be used to iterate over all nodes in
             * the column.
             *
             * @return Iterator to the end of the specified column.
             */
            const_col_iterator columnEnd(size_t end) const;
            //SplittingTreeNode *get(const size_t column, const size_t row) const;

            /**
             * Write the context to a stream.
             *
             * @return The input stream.
             */
            friend std::ostream& operator<<(std::ostream& os, const TreeContext &c);

	private:
            tree_t tree;
            size_t variableCount;
};

}


#endif  // TREECONTEXT_HPP_
